package com.fcscs.cservice.ws.endpoint;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ws.server.endpoint.annotation.Endpoint;
import org.springframework.ws.server.endpoint.annotation.PayloadRoot;
import org.springframework.ws.server.endpoint.annotation.RequestPayload;
import org.springframework.ws.server.endpoint.annotation.ResponsePayload;

import com.fcscs.core.common.MainEnums;
import com.fcscs.core.util.CommonUtil;
import com.fcscs.cservice.common.CServiceCommonEnums;
import com.fcscs.cservice.common.CServiceCommonEnums.BookingStatus;
import com.fcscs.cservice.common.CServiceCommonEnums.NotifyType;
import com.fcscs.cservice.domain.BookingBase;
import com.fcscs.cservice.domain.model.BookingHistory;
import com.fcscs.cservice.domain.model.BookingIdAndMessage;
import com.fcscs.cservice.domain.model.BookingIdAndStatus;
import com.fcscs.cservice.domain.model.BookingUpdate;
import com.fcscs.cservice.domain.model.BookingView;
import com.fcscs.cservice.domain.model.NonInHouseGuestProfile;
import com.fcscs.cservice.domain.model.RestaurantView;
import com.fcscs.cservice.service.BookingManager;
import com.fcscs.cservice.service.CServiceCommonManager;
import com.fcscs.cservice.service.RestaurantManager;
import com.fcscs.cservice.ws.schema.bookingservice.AdvancedFindBookingsRequest;
import com.fcscs.cservice.ws.schema.bookingservice.AdvancedFindBookingsResponse;
import com.fcscs.cservice.ws.schema.bookingservice.CreateBookingRequest;
import com.fcscs.cservice.ws.schema.bookingservice.CreateBookingResponse;
import com.fcscs.cservice.ws.schema.bookingservice.GetBookingHistoryRequest;
import com.fcscs.cservice.ws.schema.bookingservice.GetBookingHistoryResponse;
import com.fcscs.cservice.ws.schema.bookingservice.GetRestaurantsRequest;
import com.fcscs.cservice.ws.schema.bookingservice.GetRestaurantsResponse;
import com.fcscs.cservice.ws.schema.bookingservice.SimpleFindBookingsRequest;
import com.fcscs.cservice.ws.schema.bookingservice.SimpleFindBookingsResponse;
import com.fcscs.cservice.ws.schema.bookingservice.UpdateBookingRequest;
import com.fcscs.cservice.ws.schema.bookingservice.UpdateBookingResponse;
import com.fcscs.cservice.ws.schema.bookingservice.UpdateBookingStatusRequest;
import com.fcscs.cservice.ws.schema.bookingservice.UpdateBookingStatusResponse;
import com.fcscs.share.domain.nonexport.WsSession;
import com.fcscs.share.service.WsSessionManager;
import com.fcscs.share.util.TimezoneUtils;


@Endpoint
public class BookingServiceEndpoint {

	@Autowired
	private BookingManager bkMgr;
	
	@Autowired
	private RestaurantManager restMgr;
	
	@Autowired
	private CServiceCommonManager comMgr;
	
	@Autowired
	private WsSessionManager ssMgr;
	
	@PayloadRoot(localPart = CServiceWSConstants.GET_REST_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public GetRestaurantsResponse getRestaurants(@RequestPayload GetRestaurantsRequest req) {
		
		long orgId = CommonUtil.getWsSessionOrgId();
		Long propId = CommonUtil.getWsSessionPropertyId();
		List<RestaurantView> list = restMgr.getRestaurantViews(orgId, propId);
		//*************************************************************************
		for(RestaurantView rv : list){
			rv.setCurrency(comMgr.getCurrency(propId));
		}
		//*************************************************************************
		GetRestaurantsResponse resp = new GetRestaurantsResponse();
		resp.setRestaurantList(list);
		return resp;
	}
	
	@PayloadRoot(localPart = CServiceWSConstants.FIND_BOOK_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public SimpleFindBookingsResponse simpleFindBookings(@RequestPayload SimpleFindBookingsRequest req) {
		
		Long propId = CommonUtil.getWsSessionPropertyId();
		
		//TODO:**************************************
		MainEnums.TimeZone tz = TimezoneUtils.getTimezone(CommonUtil.getWsSessionPropertyId());
		Date currentDate = TimezoneUtils.convertToServerTimeZone(req.getReservationDate(),tz);
		//*******************************************
		List<BookingView> list = bkMgr.simFindBookings(propId, req.getRestaurantId(), req.getTerm(),currentDate, req.getStart(), req.getNumResults());
		accessTimeZone(tz, list);
		int count = bkMgr.simFindBookingsCnt( propId, req.getRestaurantId(), req.getTerm(),currentDate);
		SimpleFindBookingsResponse resp = new SimpleFindBookingsResponse();	
		resp.setBookingList(list);
		resp.setCount(count);
		return resp;
	}
	
	@PayloadRoot(localPart = CServiceWSConstants.AFIND_BOOK_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public AdvancedFindBookingsResponse advancedFindBookings(@RequestPayload AdvancedFindBookingsRequest req) {
	
		Long propId = CommonUtil.getWsSessionPropertyId();
		List<BookingStatus> ls = new ArrayList<BookingStatus>();
		if(req.getStatuList() != null){
			for(String s : req.getStatuList()){
				ls.add(BookingStatus.valueOf(s));
			}
		}
		//*******************************************
		MainEnums.TimeZone tz = TimezoneUtils.getTimezone(CommonUtil.getWsSessionPropertyId());
		Date startDate =TimezoneUtils.convertToServerTimeZone(req.getStartDate(), tz);
		Date endDate = TimezoneUtils.convertToServerTimeZone(req.getEndDate(), tz);
		Date reservationDate = TimezoneUtils.convertToServerTimeZone(req.getReservationDate(), tz);
		//************************************************
		//Added guestProfile type
		List<BookingView> list = bkMgr.findBookings( propId, req.getRestaurantId(), null, req.getFirstName(), req.getLastName(),
				req.getMobileNo(),null,reservationDate,ls,startDate,endDate, req.getStart(), req.getNumResults(), null, true);
		accessTimeZone(tz, list);
		int count = bkMgr.findBookingsCnt(propId, req.getRestaurantId(), null, req.getFirstName(), req.getLastName(),
				req.getMobileNo(),null, reservationDate, ls,startDate,endDate);
		
		AdvancedFindBookingsResponse resp = new AdvancedFindBookingsResponse();
		resp.setBookingList(list);
		resp.setCount(count);
		return resp;
	}

	private void accessTimeZone(MainEnums.TimeZone tz, List<BookingView> list) {
		for(BookingView bv : list){
			bv.setArrivalDate(TimezoneUtils.convertToLocalTimeZone(bv.getArrivalDate(),tz));
			bv.setDepartureDate(TimezoneUtils.convertToLocalTimeZone(bv.getDepartureDate(),tz));
			bv.setCreated(TimezoneUtils.convertToLocalTimeZone(bv.getCreated(),tz));
			bv.setReservationDate(TimezoneUtils.convertToLocalTimeZone(bv.getReservationDate(),tz));
		}
	}

	@PayloadRoot(localPart = CServiceWSConstants.UPDATE_BOOKING_STU_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public UpdateBookingStatusResponse getUpdateBookingStatus(@RequestPayload UpdateBookingStatusRequest req) {
		
		boolean isValidaor = false;
		Long propId = CommonUtil.getWsSessionPropertyId();
		List<BookingIdAndStatus> idstatus = req.getBookingIdAndStatuList();
		UpdateBookingStatusResponse resp = new UpdateBookingStatusResponse();
		for(BookingIdAndStatus bias : idstatus){
			if(progress(bias.getBookingStatus())){
				isValidaor = true;
			}else{
				resp.setBookingIdAndMessageList(null);
				isValidaor = false;
				break;
			}
		}
		if(isValidaor){
			List<BookingIdAndMessage> list = bkMgr.updateBookingStatus(propId, idstatus);
			resp.setBookingIdAndMessageList(list);
		}
		return resp;
	}
	
	@PayloadRoot(localPart = CServiceWSConstants.GET_BOOKING_HISTORY_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public GetBookingHistoryResponse getBookingHistory(@RequestPayload GetBookingHistoryRequest req) {
		
		long guestId = req.getGuestId();
		Long propId = CommonUtil.getWsSessionPropertyId();
		List<BookingView> listView = bkMgr.getBookingHistory( propId, guestId, req.getStart(), req.getNumResults());
		int resultNum = bkMgr.getBookingHistoryCnt( propId, guestId);
		GetBookingHistoryResponse resp = new GetBookingHistoryResponse();
		BookingHistory bh = new BookingHistory();
		bh.setGuestId(guestId);
		bh.setBookingViewList(listView);
		resp.setBookingHistory(bh);
		resp.setCount(resultNum);
		
		return resp;
	}
	
	@PayloadRoot(localPart = CServiceWSConstants.UPDATE_BOOKING_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public UpdateBookingResponse getUpdateBooking(@RequestPayload UpdateBookingRequest req) {
		// bookingId and guestId not null
		if(req.getBookingId() <= 0 || req.getInHoGuestProId() <= 0 ){
			UpdateBookingResponse up = new UpdateBookingResponse();
			up.setUpdateStatusMsg(CServiceCommonEnums.StatusMessage.MISSING_REQUIRED_FIELD.toString());
			return up;
		}
		Long propId = CommonUtil.getWsSessionPropertyId();
		BookingUpdate bu = new BookingUpdate();
		bu.setBookingId(req.getBookingId());
		if(req.getBookingStatus() != null){
			if(progress(req.getBookingStatus())){
				bu.setBookingStatus(BookingStatus.valueOf(req.getBookingStatus()));
			}else{
				UpdateBookingResponse up = new UpdateBookingResponse();
				up.setUpdateStatusMsg(CServiceCommonEnums.StatusMessage.MISSING_REQUIRED_FIELD.toString());
				return up;
			}
		}
//		MainEnums.TimeZone tz =MainEnums.TimeZone.NST;//+12
		MainEnums.TimeZone tz = TimezoneUtils.getTimezone(CommonUtil.getWsSessionPropertyId());
		//progress localDate to serverDate
		bu.setArrivalDate(TimezoneUtils.convertToServerTimeZone(req.getArriveDate(),tz));
		bu.setReservationDate(TimezoneUtils.convertToServerTimeZone(req.getReservationDate(),tz));
		bu.setDepartureDate(TimezoneUtils.convertToServerTimeZone(req.getDepartureDate(),tz));
		bu.setEamil(req.getEmail());
		bu.setGender(req.getGender());
		bu.setGuestFirstName(req.getFirstName());
		bu.setGuestId(req.getInHoGuestProId());
		bu.setGuestLastName(req.getLastName());
		bu.setNoOfGuest(req.getNoOfGuest());
		bu.setNote(req.getNote());
		List<NotifyType> list = new ArrayList<NotifyType>();
		if(req.getNotifyList() != null){
			for(String s: req.getNotifyList()){
				list.add(NotifyType.valueOf(s));
			}
		}
		bu.setNotifyList(list);
		bu.setPhoneNumber(req.getPhoneNumber());
		bu.setPropertyId(propId);
		bu.setRestaurantId(req.getRestaurantId());
		bu.setSmoking(req.getSmoking());
		BookingView bv = bkMgr.updateBooking(bu);
		//progress serverDate to localDate
		UpdateBookingResponse resp = new UpdateBookingResponse();
		if(bv != null){
			bv.setReservationDate(TimezoneUtils.convertToLocalTimeZone(bv.getReservationDate(),tz));
			if(bv.getArrivalDate() != null){
				bv.setArrivalDate(TimezoneUtils.convertToLocalTimeZone(bv.getArrivalDate(),tz));
			}
			if(bv.getDepartureDate() != null){
				bv.setDepartureDate(TimezoneUtils.convertToLocalTimeZone(bv.getDepartureDate(),tz));
			}
			resp.setBooking(bv);
//			resp.setUpdateStatusMsg(CServiceCommonEnums.StatusMessage.SUCCESS.toString());
		}else{
			resp.setUpdateStatusMsg(CServiceCommonEnums.StatusMessage.FAILED.toString());
		}
		
		return resp;
	}
	
	private boolean progress(String bookingStatus) {
		boolean target = false;
		for(BookingStatus bs :BookingStatus.values()){
			if(bookingStatus.equals(bs.toString())){
				target = true;
				break;
			}
		}
		return target;
	}


	@PayloadRoot(localPart = CServiceWSConstants.CREATE_BOOKING_REQ, namespace = CServiceWSConstants.BOOK_SERVICE_NAMESPACE_URI)
	@ResponsePayload
	public CreateBookingResponse getCreateBooking(@RequestPayload CreateBookingRequest req) {

		if(req.getNonInHouseGuestProfile()== null && req.getInHoGuestProId() == null){
			CreateBookingResponse resp = new CreateBookingResponse();
			resp.setCreateStatusMsg(CServiceCommonEnums.StatusMessage.MISSING_REQUIRED_FIELD.toString());
			return resp;
		}else if(req.getNonInHouseGuestProfile() != null && req.getInHoGuestProId() != null){
			CreateBookingResponse resp = new CreateBookingResponse();
			resp.setCreateStatusMsg(CServiceCommonEnums.StatusMessage.MISSING_REQUIRED_FIELD.toString());
			return resp;
		}
		NonInHouseGuestProfile nonGuest = req.getNonInHouseGuestProfile();
		BookingBase bkBase = new BookingBase();
		bkBase.setOrgId(CommonUtil.getWsSessionOrgId());
		bkBase.setPropertyId(CommonUtil.getWsSessionPropertyId());
		bkBase.setBookingStatus(req.getBookingStatus());
		bkBase.setNote(req.getNote());
		bkBase.setNumberOfGuest(req.getNoOfGuest());
		bkBase.setReservationDate(req.getReservationDate());
		bkBase.setRestaurantId(req.getRestaurantId());
		if(req.getSmoking() == null){
			bkBase.setSmoking(Boolean.FALSE);
		}else{
			bkBase.setSmoking(req.getSmoking());
		}
		List<NotifyType> list = new ArrayList<NotifyType>();
		if(req.getNotifyList() != null){
			for(String s: req.getNotifyList()){
				list.add(NotifyType.valueOf(s));
			}
		}
		bkBase.setNotifyList(list);
		bkBase.setGuestType(req.getGuestType());  
		if(req.getInHoGuestProId() != null){
			bkBase.setGuestProfileId(req.getInHoGuestProId());
		}
		Long userId = CommonUtil.getWsSessionUserId();
		if (userId != null) {
			WsSession ss = ssMgr.getSession(userId);
			if (ss != null) {
				bkBase.setSourceEnum(ss.getSourceEnum());
			}
		}
		BookingView bv1 = bkMgr.createBooking(bkBase,nonGuest);
		CreateBookingResponse resp = new CreateBookingResponse();
		if(bv1 != null){
			resp.setBooking(bv1);
//			resp.setCreateStatusMsg(CServiceCommonEnums.StatusMessage.SUCCESS.toString());
		}else{
			resp.setCreateStatusMsg(CServiceCommonEnums.StatusMessage.FAILED.toString());
		}
		
		return resp;
	}
}
